Default theme architecture, external layer, and docs restructure - #67
Merged
Conversation
settings.tokens.css and settings.ui.css move to theme.default.tokens.css and theme.default.ui.css, each self-layered into the new theme.defaults sublayer, with a theme.default.css entry importing both. mcss.css drops the settings layer and imports, and declares theme.defaults + theme.overrides in the layer order; user themes land in theme.overrides so they beat the default regardless of import order. The site entry (_global.css) activates the default theme explicitly. mcss.css alone no longer paints a page: the default theme carries every design value. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
theme.wireframe.css now imports the default theme and lands its own overrides in theme.overrides, making it a self-contained swappable skin: activate it INSTEAD of theme.default.css. The marketing template's pinned layer statement follows the new order. The old empty theme.default.css template role moves to theme.starter.css, pre-wrapped in theme.overrides with the same guidelines. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A composed brand gradient is site content, not a scale step. The marketing template's hero inlines it; the token is gone. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
dist/mcss.css and dist/mcss.min.css now bundle theme.default.css so the one-file drop-in keeps painting a complete default look. The dist/css index activates the default theme import (the framework doesn't paint without one), marks its two parts as imported by the entry, and leaves other theme entries commented for swapping. Layer statement and prefix map drop the retired settings layer; the theme.default.css per-file output passes through untouched (imports only). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… tokens Every reference to settings.tokens.css / settings.ui.css follows the files into theme.default.*; the term interface tokens dies in favor of ui tokens everywhere (docs pages, component pages, agents docs, CLAUDE.md, blog structure post's kept-current list, homepage copy, llms.txt pointer). start.mdx, themes.mdx, tokens.mdx, and ai.mdx teach the new model: the framework is structure plus a default theme you activate and never edit; your theme overrides it from theme.overrides regardless of import order; the ownership rule now has no exceptions (the edit-tokens-at-setup guidance is gone). The AI rules block and skill mirror are synced. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Layer priority is set by first declaration, so a theme file parsed before mcss.css used to establish the wrong order (theme before base). theme.default.css, theme.starter.css, and theme.wireframe.css now open with the canonical @layer statement, the same trick the marketing template uses inline: whichever framework file loads first pins the correct order, and a user override loaded before the framework still wins. Verified in-browser: override-before-framework wins, wireframe skin renders over the composed default, dist/mcss.min.css alone paints the complete default look. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The parts aren't standalone themes, they're internal files with one blessed loader, so theme.default.css assigns layer(theme.defaults) on its imports the same way mcss.css layers the structural files, and the part files go back to flat, unwrapped CSS. Only standalone theme files (starter, skins) still self-layer. The dist build pre-wraps the dist copies of the parts so a lone <link> on one still slots correctly. agents/css.md and CLAUDE.md state the refined convention: files a consumer loads directly self-layer; files an entry imports are layered by the entry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
theme.defaults becomes theme.default, so the layer name matches the theme.default.* file prefix exactly instead of differing by a plural. theme.overrides becomes theme.user: overrides was redundant (every later layer overrides earlier ones); user names whose slot it is and pairs naturally with default. (default is safe as a layer name: the reservation applies to custom-ident contexts, and layer names take plain idents; verified parsing in-browser.) Swept across the framework, build script, marketing template pin, docs, blog note, and the AI block + skill mirror. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The --success/danger/warning-* aliases over --yes/no/maybe-* were a synonym layer: the raw palettes are already semantically named, and adoption was split (notices and button variants consumed the raw scales), so overriding an alias silently missed half the feedback surfaces. Everything now consumes the palettes directly, the fifteen alias declarations are gone, and the docs plus AI block and skill mirror state the single-vocabulary rule. Component token names like --badge-success-color keep their variant names; only their values changed. Computed values are identical. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
"The import below brings in every default" read as if the defaults were in this file; say instead that the file contains only the skin's deviations and the @import makes the browser load theme.default.css alongside it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add an explicit npm run check:layers step and tighten dist verification. Replace fragile layer greps with checks that detect cascade-layers/light-dark polyfill artifacts and csstools output, require the default theme to be baked into dist/mcss.css, and ensure components and user themes are only present in their own bundles. Also validate standalone theme files self-layer as theme.user and prevent unresolved custom-media/mixin syntax from shipping.
The marketing template imported only mcss.css, which since the default theme restructure carries no design values (nothing paints without theme.default.css) and no component styles either. Import both alongside it, the same way any consumer entry does. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Remove several redundant preview/dev entries, normalize runtimeArgs formatting, and replace the old dev-4340 entry with a single preview configuration on port 4400. Keeps the existing dev entry on port 4321.
Add scroll-padding-block-start to account for the sticky site header so in-page anchor targets do not land hidden beneath the header.
✅ Deploy Preview for mcssdev ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Owner
Author
|
Redirect verification: done (against the Netlify deploy preview), closing out the "post-deploy check owed" item from the PR description. All 18 retired/legacy URLs return real edge 301s with correct targets:
🤖 Verified by Claude Code |
minimaldesign
added a commit
that referenced
this pull request
Aug 17, 2026
The 1.4.0 bump landed on default-theme after #67 was already merged; this brings it to main. 1.4.0 rather than 2.0.0 because versions here mark copyable states of the repo, not an API contract, and 1.2.0/1.3.0 already shipped breaking changes as minors with a Breaking changelog section. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

What changed
Framework
theme.default.css(importingtheme.default.tokens.css+theme.default.ui.css). The framework doesn't paint without it; consumer entries activate it right aftermcss.css.theme.defaultandtheme.user; theme entries pin the layer order so they slot correctly no matter how they're loaded.externallayer (betweentheme.userandhelpers): an empty slot to demote third-party CSS (@import url(vendor.css) layer(external)) so it beats the framework but loses to all project CSS. Companionpatch.*.cssconvention for fixes to vendor styles (site'sexternal.astro.cssrenamed accordingly).theme.starter.cssas the starting point for user themes.--yes-*/--no-*/--maybe-*palettes directly.Build & CI
dist/mcss.cssbakes the default theme in so the drop-in stays a working single file;dist/css/mcss.cssindex is ordered by cascade layer with accurate per-theme comments.@layerstatement is derived frommcss.cssat build time, and a newcheck-layers.mjs(pre-commit + CI) verifies every other copy (theme pins, docs code blocks, dist) agrees.--fixmode rewrites stale copies.theme.userskins, nocsstoolspolyfill artifacts).Docs
public/_redirectsas real Netlify 301s (theastro.config.mjsredirects block is gone and must stay gone: its meta-refresh stubs shadow the edge rules and break.mdtwin fetchers). Every retired URL has a rule for both the HTML page and its.mdtwin.mcss.components.cssandtheme.default.css(it painted nothing after the restructure).scroll-padding-block-starton the root).Why
The default theme restructure makes the framework/theme boundary real: structure ships in layers, every design value lives in one swappable place, and user themes override it predictably. The docs restructure retires the file-taxonomy nav for pages organized around what a reader is trying to do.
Reviewer notes
_redirects; framework consumers need the new theme activation line..mdforms) on the live site to confirm Netlify serves real 301s;_redirectsis new and can't be fully verified locally.check-layers.mjsis the guard against the layer statement drifting between its (deliberately) duplicated copies; runnpm run check:layers -- --fixafter any layer change.Closes #65